<?php

class Think {

    private static $_instance = array();

    /**
     * 功能：预编译项目
     */
    static public function Start() {
        Think::buildApp();         // 预编译项目
        return ;
    }


    /**
     * 功能：读取配置信息，编译文件
     * 编译的文件有：
     * 1.6个应用类核心函数编译
     * 2.项目中conf中core.php文件数组（用户自定义类或者函数文件），
     * 3.加载项目的公共文件 编译
     * 4.项目别名定义文件的编译
     * 依赖全局函数 build_runtime_cache
     * 该函数编译的文件有：
     * 0.运行起始全局时间微秒数
     * 1.用户定义的常量 编译到文件
     * 2.系统的4个核心类编译到文件一个系统公共函数，3个核心类
     * 3.系统行为扩展类文件 编译到文件依赖build_tags_cache
     * 4.系统的别名定义编译到文件
     * 5.编译框架默认语言包和配置参数以及加载时间,以及框架运行入口
     */
    static private function buildApp() {
        // 加载系统底层配置文件
        C(include TPCORE_PATH.'Conf/convention.php');

        // 加载框架底层语言包
        L(include TPCORE_PATH.'Lang/'.strtolower(C('DEFAULT_LANG')).'.php');

        // 加载项目配置文件
        if(is_file(CONF_PATH.'config.php')) C(include CONF_PATH.'config.php');



        ////////////////////////针对框架运行模式//////////////////////////////////

        // 读取框架的运行模式 有cli模式restful模式等等以后在逐个看，默认不配置使用默认模式
        if(defined('MODE_NAME')) {
            //引入该模式文件
            $mode   = include MODE_PATH.strtolower(MODE_NAME).'.php';
        }else{
            $mode   =  array();
        }

        // 如果运行模式中配置config选项，引入根据情况引入配置
        if(isset($mode['config'])) {
            C( is_array($mode['config'])?$mode['config']:include $mode['config'] );
        }


        // 系统行为扩展开启，运行模式中设置过该选项，根据情况引入配置扩展，否则默认加载系统行为扩展定义
        if(C('APP_TAGS_ON')) {
            if(isset($mode['extends'])) {
                C('extends',is_array($mode['extends'])?$mode['extends']:include $mode['extends']);
            }else{
                C('extends', include TPCORE_PATH.'Conf/tags.php');
            }
        }

        // 运行模式中是否设置标签项，设置过该选项，设置过使用配置中的文件引入该项，否则
        // 默认加载项目配置目录的tags文件定义
        if(isset($mode['tags'])) {
            C('tags', is_array($mode['tags'])?$mode['tags']:include $mode['tags']);
        }elseif(is_file(CONF_PATH.'tags.php')){

            C('tags', include CONF_PATH.'tags.php');
        }
        ////////////////////////针对框架运行模式//////////////////////////////////


        $compile   = ''; //初始化编译字符串

        $tptool=APP_PATH."TpTool.php";//哈哈项目编译的一些核心全局函数被我拎出来了,记得写到编译文件中
        if(!APP_DEBUG)   $compile .= compile($tptool);//该文件已被加载过无需重复加载
        /////////////////////////////////系统核心类或用户自定义类函数编译////////////////
        // 读取应用类核心函数编译文件列表
        if(isset($mode['core'])) {
            $list   =  $mode['core'];
        }else{
            $list  =  array(
                TPCORE_PATH.'Common/functions.php', // 标准模式函数库
                CORE_PATH.'Core/Log.class.php',    // 日志处理类
                CORE_PATH.'Core/Dispatcher.class.php', // URL调度类
                CORE_PATH.'Core/App.class.php',   // 应用程序类
                CORE_PATH.'Core/Action.class.php', // 控制器类
                CORE_PATH.'Core/View.class.php',  // 视图类
            );
        }

        // 项目应用中conf中core.php文件(core.php文件中用户自定义载入文件路径[文件路径,文件路径])
        if(is_file(CONF_PATH.'core.php')) {
            $list  =  array_merge($list,include CONF_PATH.'core.php');
        }
        //将用户自定义类函数，或者配置文件，载入,未开启debug，追加到编译文件中
        foreach ($list as $file){
            if(is_file($file))  {
                require_cache($file);
                if(!APP_DEBUG)   $compile .= compile($file);
            }
        }
        /////////////////////////////////系统核心类或用户自定义类函数编译////////////////


        //////////////////////////////// 加载项目的公共文件or编译到文件/////////////////
        if(is_file(COMMON_PATH.'common.php')) {
            include COMMON_PATH.'common.php';
            // 编译文件
            if(!APP_DEBUG)  $compile   .= compile(COMMON_PATH.'common.php');
        }
        //////////////////////////////// 加载项目的公共文件or编译到文件/////////////////



       //////////////////////////////// 加载定义别名 or 别名定义到编译文件////////////
        // 加载编译文件中别名定义(编译文件不存在不执行)
        if(isset($mode['alias'])) {
            $alias = is_array($mode['alias'])?$mode['alias']:include $mode['alias'];
            alias_import($alias);
            if(!APP_DEBUG) $compile .= 'alias_import('.var_export($alias,true).');';
        }
        // 加载项目别名定义alias.php(返回的是数组 [别名=>文件路径]) 通过var_export把数组结构拼接到         //函数中写入到编译文件中，供后续编译文件执行直接调用
        if(is_file(CONF_PATH.'alias.php')){ 
            $alias = include CONF_PATH.'alias.php';
            alias_import($alias);
            if(!APP_DEBUG) $compile .= 'alias_import('.var_export($alias,true).');';
        }
        //////////////////////////////// 加载定义别名 or 别名定义到编译文件////////////

        //如果当前是调试模式? 载入调试模式配置项 : 直接在部署的项目中生成编译文件
        if(APP_DEBUG) {
            // 调试模式加载系统默认的配置文件
            C(include THINK_PATH.'Conf/debug.php');
            // 读取调试模式的应用状态
            $status  =  C('APP_STATUS');
            // 加载用户项目配置调试模式文件，该文件肯能会覆盖上面系统配置文件的参数
            if(is_file(CONF_PATH.$status.'.php'))
                // 允许项目增加开发模式配置定义
                C(include CONF_PATH.$status.'.php');
        }else{
            // 部署模式下面生成编译文件
            build_runtime_cache($compile);
        }
        return ;
    }

}